import { EcsEntity } from "./EcsEntity";

function _sortEntityById(a: EcsEntity, b: EcsEntity) {
	if (a.id < b.id)
		return -1
	else
		return 1
}
export class EcsEntityGroup {
	public entities: EcsEntity[] = [];
	public compIds: number[] = [];
	public compIdMap: { [key: number]: boolean } = {};
	public indexMap: { [key: number]: number } = {}

	hasEntity(entity: EcsEntity): boolean {
		return this.indexMap[entity.id] != undefined
	}

	/**从entites列表中最后一个元素向前遍历，防止删除列表元素时的错位问题 */
	public forEach(callbackfn: (value: EcsEntity, index: number, array: EcsEntity[]) => void, thisArg?: any) {
		if (!thisArg) thisArg = this

		for (let index = this.entities.length - 1; index >= 0; index--) {
			const element = this.entities[index];
			callbackfn.call(thisArg, element, index, this.entities)
		}
	}

	public constructor(compIds: number[], entities: { [key: number]: EcsEntity }) {
		this.compIds = compIds;
		for (let i = 0; i < compIds.length; i++) {
			this.compIdMap[compIds[i]] = true;
		}
		for (let k in entities) {
			let _entity = entities[k];
			let _compsID: string = _entity.groupId;
			if (_entity.hasAllCompIds(...compIds)) {
				this.entities.push(_entity);
			}
		}
		this.entities.sort(_sortEntityById);

		for (let index = 0; index < this.entities.length; index++) {
			const entity = this.entities[index];
			this.indexMap[entity.id] = index
		}
	}

	public add( entity: EcsEntity): void {
		this.entities.push(entity);
		this.indexMap[entity.id] = this.entities.length - 1
	}

	public remove( entity: EcsEntity): void {
		const index = this.indexMap[entity.id]
		if (index || index == 0) {
			delete this.indexMap[entity.id]
			this.entities[index] = this.entities[this.entities.length - 1]
			const switchEcsEntity = this.entities[index]
			if (switchEcsEntity !== entity) {
				this.indexMap[switchEcsEntity.id] = index
			}
			this.entities.length -= 1
		}
	}

	isMatch(entity: EcsEntity): boolean {
		for (let i = 0; i < this.compIds.length; i++) {
			if (!entity.componentMap.has(this.compIds[i])) {
				return false;
			}
		}
		return true;
	}

	
}